// $Id: WorkitemView.java 85 2012-02-25 15:01:58Z huijzer@gmail.com $
package lime.workflow.view;

import lime.Activator;
import lime.application.view.Refreshable;
import lime.common.LimeException;
import lime.model.Workitem;
import lime.service.SpringApplicationContext;
import lime.service.WorkflowService;
import lime.workflow.provider.WorkitemContentProvider;
import lime.workflow.provider.WorkitemLabelProvider;

import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;

public class WorkitemView extends ViewPart implements Refreshable, IPropertyChangeListener {

	public static final String ID = "lime.workflow.view.workitem";

	private IPreferenceStore preferenceStore;
	private WorkitemColorer colorer;
	private boolean autoRefresh;
	private boolean running;

	// Widgets
	private TableViewer viewer;

	// Services
	private WorkflowService workflowService;

	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		workflowService = (WorkflowService) SpringApplicationContext.getBean("workflowService");
		preferenceStore = Activator.getDefault().getPreferenceStore();
		preferenceStore.addPropertyChangeListener(this);
		colorer = new WorkitemColorer();
	}

	@Override
	public void createPartControl(Composite parent) {

		viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER);
		viewer.getTable().setHeaderVisible(true);
		viewer.getTable().setLinesVisible(true);

		TableViewerColumn workflowStartColumn = new TableViewerColumn(viewer, SWT.NONE);
		workflowStartColumn.getColumn().setText("Workflow Start");

		TableViewerColumn processNameColumn = new TableViewerColumn(viewer, SWT.NONE);
		processNameColumn.getColumn().setText("Process Name");

		TableViewerColumn workitemStartColumn = new TableViewerColumn(viewer, SWT.NONE);
		workitemStartColumn.getColumn().setText("Workitem Start");

		TableViewerColumn activityNameColumn = new TableViewerColumn(viewer, SWT.NONE);
		activityNameColumn.getColumn().setText("Activity Name");

		TableViewerColumn performerNameColumn = new TableViewerColumn(viewer, SWT.NONE);
		performerNameColumn.getColumn().setText("Performer Name");

		TableViewerColumn runtimeStateColumn = new TableViewerColumn(viewer, SWT.NONE);
		runtimeStateColumn.getColumn().setText("Runtime State");

		viewer.setContentProvider(new WorkitemContentProvider());
		viewer.setLabelProvider(new WorkitemLabelProvider());
		viewer.setInput(workflowService.getWorkitems());

		viewer.getTable().addListener(SWT.EraseItem, new Listener() {
			@Override
			public void handleEvent(Event event) {
				TableItem tableItem = (TableItem) event.item;
				Workitem workitem = (Workitem) tableItem.getData();
				Color tempColor = colorer.getColor(workitem);
				GC gc = event.gc;

				int clientWidth = viewer.getTable().getClientArea().width;
				Color oldForeground = gc.getForeground();
				Color oldBackground = gc.getBackground();
				gc.setForeground(tempColor);
				gc.setBackground(tempColor);
				gc.fillRectangle(0, event.y, clientWidth, event.height);
				gc.setForeground(oldForeground);
				gc.setBackground(oldBackground);
			}
		});

		// Add context menu
		MenuManager menuManager = new MenuManager();
		menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		viewer.getTable().setMenu(menuManager.createContextMenu(viewer.getTable()));
		getSite().registerContextMenu(menuManager, viewer);
		getSite().setSelectionProvider(viewer);

		// Make sure the columns take up as much space as needed, but not more.
		for (TableColumn column : viewer.getTable().getColumns()) {
			column.pack();
		}
	}

	@Override
	public void setFocus() {
		viewer.getTable().setFocus();
	}

	@Override
	public void refresh() {
		viewer.setInput(workflowService.getWorkitems(getFilter()));
		// Resizing the columns will introduce flickering
		// for (TableColumn column : viewer.getTable().getColumns()) {
		// column.pack();
		// }
	}

	@Override
	public void propertyChange(PropertyChangeEvent event) {
		colorer.reload();
		viewer.getTable().redraw();
	}

	public void setAutoRefresh(boolean autoRefresh) {
		this.autoRefresh = autoRefresh;
		if (autoRefresh && !running) {
			AutoRefreshRunner runner = new AutoRefreshRunner();
			runner.start();
		}
	}

	public class AutoRefreshRunner extends Thread {
		@Override
		public void run() {
			running = true;
			while (autoRefresh) {
				getSite().getShell().getDisplay().asyncExec(new Runnable() {
					public void run() {
						refresh();
					}
				});
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					throw new LimeException(e);
				}
			}
			running = false;
		}
	}

	private IWorkitemFilter getFilter() {
		FilterView filterView = (FilterView) getSite().getPage().findView(FilterView.ID);
		if (filterView != null) {
			return filterView.getFilter();
		} else {
			return new DefaultWorkitemFilter();
		}
	}
}
